package net.yegong.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

public class Time {

	public Time() {
		calendar = new GregorianCalendar();
	}

	public Time(long time) {
		calendar = new GregorianCalendar();
		calendar.setTimeInMillis(time);
	}

	public long getTime() {
		return calendar.getTimeInMillis();
	}

	public long thisSecond() {
		Calendar carl = (Calendar) calendar.clone();
		carl.clear(Calendar.MILLISECOND);
		return carl.getTimeInMillis();
	}

	public long thisMinute() {
		Calendar carl = (Calendar) calendar.clone();
		carl.clear(Calendar.MILLISECOND);
		carl.clear(Calendar.SECOND);
		return carl.getTimeInMillis();
	}

	public long nextMinute(int second) {
		Calendar carl = (Calendar) calendar.clone();
		carl.setTimeInMillis(thisMinute());
		carl.set(Calendar.SECOND, second);
		if (carl.getTimeInMillis() <= calendar.getTimeInMillis()) {
			carl.add(Calendar.MINUTE, 1);
		}
		return carl.getTimeInMillis();
	}

	public long nextMinute(String str) throws ParseException {
		try {
			return nextMinute(Integer.parseInt(str));
		} catch (NumberFormatException e) {
		}
		throw new ParseException(str, 0);
	}

	public long thisHour() {
		Calendar carl = (Calendar) calendar.clone();
		carl.clear(Calendar.MILLISECOND);
		carl.clear(Calendar.SECOND);
		carl.clear(Calendar.MINUTE);
		return carl.getTimeInMillis();
	}

	public long nextHour(int minute, int second) {
		Calendar carl = (Calendar) calendar.clone();
		carl.setTimeInMillis(thisHour());
		carl.set(Calendar.MINUTE, minute);
		carl.set(Calendar.SECOND, second);
		if (carl.getTimeInMillis() <= calendar.getTimeInMillis()) {
			carl.add(Calendar.HOUR, 1);
		}
		return carl.getTimeInMillis();
	}

	public long nextHour(String str) throws ParseException {
		try {
			String[] array = str.split(":");
			if (2 == array.length) {
				return nextHour(Integer.parseInt(array[0]), Integer.parseInt(array[1]));
			}
		} catch (NumberFormatException e) {
		}
		throw new ParseException(str, 0);
	}

	public long thisDay() {
		Calendar carl = (Calendar) calendar.clone();
		carl.clear(Calendar.MILLISECOND);
		carl.clear(Calendar.SECOND);
		carl.clear(Calendar.MINUTE);
		carl.clear(Calendar.AM_PM);
		carl.clear(Calendar.HOUR);
		carl.clear(Calendar.HOUR_OF_DAY);
		return carl.getTimeInMillis();
	}

	public long nextDay(int hour, int minute, int second) {
		Calendar carl = (Calendar) calendar.clone();
		carl.setTimeInMillis(thisHour());
		carl.set(Calendar.HOUR_OF_DAY, hour);
		carl.set(Calendar.MINUTE, minute);
		carl.set(Calendar.SECOND, second);
		if (carl.getTimeInMillis() <= calendar.getTimeInMillis()) {
			carl.add(Calendar.DAY_OF_MONTH, 1);
		}
		return carl.getTimeInMillis();
	}

	public long nextDay(String str) throws ParseException {
		try {
			String[] array = str.split(":");
			if (3 == array.length) {
				return nextDay(Integer.parseInt(array[0]), Integer.parseInt(array[1]), Integer.parseInt(array[2]));
			}
		} catch (NumberFormatException e) {
		}
		throw new ParseException(str, 0);
	}

	public long thisWeek() {
		Calendar carl = (Calendar) calendar.clone();
		carl.clear(Calendar.MILLISECOND);
		carl.clear(Calendar.SECOND);
		carl.clear(Calendar.MINUTE);
		carl.clear(Calendar.AM_PM);
		carl.clear(Calendar.HOUR);
		carl.clear(Calendar.HOUR_OF_DAY);
		carl.set(Calendar.DAY_OF_WEEK, carl.getFirstDayOfWeek());
		return carl.getTimeInMillis();
	}

	public long nextWeek(int dayOfWeek, int hour, int minute, int second) {
		Calendar carl = (Calendar) calendar.clone();
		carl.setTimeInMillis(thisHour());
		carl.set(Calendar.DAY_OF_WEEK, dayOfWeek);
		carl.set(Calendar.HOUR_OF_DAY, hour);
		carl.set(Calendar.MINUTE, minute);
		carl.set(Calendar.SECOND, second);
		if (carl.getTimeInMillis() <= calendar.getTimeInMillis()) {
			carl.add(Calendar.WEEK_OF_YEAR, 1);
		}
		return carl.getTimeInMillis();
	}

	public long nextWeek(String str) throws ParseException {
		try {
			String[] array = str.split(" ");
			if (2 != array.length) {
				throw new ParseException(str, 0);
			}
			String week = array[0].toUpperCase();
			String time = array[1];
			String[] timeArray = time.split(":");
			if (3 != timeArray.length) {
				throw new ParseException(time, 0);
			}
			if (!DAY_IN_WEEK_MAPPING.containsKey(week)) {
				throw new ParseException(str, 0);
			}
			return nextWeek(DAY_IN_WEEK_MAPPING.get(week), Integer.parseInt(timeArray[0]), Integer.parseInt(timeArray[1]), Integer.parseInt(timeArray[2]));
		} catch (NumberFormatException e) {
		}
		throw new ParseException(str, 0);
	}

	public long thisMonth() {
		Calendar carl = (Calendar) calendar.clone();
		carl.clear(Calendar.MILLISECOND);
		carl.clear(Calendar.SECOND);
		carl.clear(Calendar.MINUTE);
		carl.clear(Calendar.AM_PM);
		carl.clear(Calendar.HOUR);
		carl.clear(Calendar.HOUR_OF_DAY);
		carl.set(Calendar.DAY_OF_MONTH, 1);
		return carl.getTimeInMillis();
	}

	public long nextMonth(int day, int hour, int minute, int second) {
		Calendar carl = (Calendar) calendar.clone();
		carl.setTimeInMillis(thisHour());
		carl.set(Calendar.DAY_OF_MONTH, day);
		carl.set(Calendar.HOUR_OF_DAY, hour);
		carl.set(Calendar.MINUTE, minute);
		carl.set(Calendar.SECOND, second);
		if (carl.getTimeInMillis() <= calendar.getTimeInMillis()) {
			carl.add(Calendar.MONTH, 1);
		}
		return carl.getTimeInMillis();
	}

	public String toString() {
		return FORMAT.format(calendar.getTime());
	}

	protected final static Map<String, Integer> DAY_IN_WEEK_MAPPING;
	protected final static DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	protected final Calendar calendar;

	static {
		DAY_IN_WEEK_MAPPING = new HashMap<String, Integer>();
		DAY_IN_WEEK_MAPPING.put("MONDAY", Calendar.MONDAY);
		DAY_IN_WEEK_MAPPING.put("TUESDAY", Calendar.TUESDAY);
		DAY_IN_WEEK_MAPPING.put("WEDNESDAY", Calendar.WEDNESDAY);
		DAY_IN_WEEK_MAPPING.put("THURSDAY", Calendar.THURSDAY);
		DAY_IN_WEEK_MAPPING.put("FRIDAY", Calendar.FRIDAY);
		DAY_IN_WEEK_MAPPING.put("SATURDAY", Calendar.SATURDAY);
		DAY_IN_WEEK_MAPPING.put("SUNDAY", Calendar.SUNDAY);

		DAY_IN_WEEK_MAPPING.put("MON", Calendar.MONDAY);
		DAY_IN_WEEK_MAPPING.put("TUE", Calendar.TUESDAY);
		DAY_IN_WEEK_MAPPING.put("WED", Calendar.WEDNESDAY);
		DAY_IN_WEEK_MAPPING.put("THU", Calendar.THURSDAY);
		DAY_IN_WEEK_MAPPING.put("FRI", Calendar.FRIDAY);
		DAY_IN_WEEK_MAPPING.put("SAT", Calendar.SATURDAY);
		DAY_IN_WEEK_MAPPING.put("SUN", Calendar.SUNDAY);

		DAY_IN_WEEK_MAPPING.put("MON.", Calendar.MONDAY);
		DAY_IN_WEEK_MAPPING.put("TUE.", Calendar.TUESDAY);
		DAY_IN_WEEK_MAPPING.put("WED.", Calendar.WEDNESDAY);
		DAY_IN_WEEK_MAPPING.put("THU.", Calendar.THURSDAY);
		DAY_IN_WEEK_MAPPING.put("FRI.", Calendar.FRIDAY);
		DAY_IN_WEEK_MAPPING.put("SAT.", Calendar.SATURDAY);
		DAY_IN_WEEK_MAPPING.put("SUN.", Calendar.SUNDAY);
	}
}
